package com.weimob.mcloud.wechatwork.customer.export;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.weimob.mcloud.wechatwork.common.enums.CommonBizErrorEnum;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.bc.request.BcGetCorpByPidOrBosIdRequestDTO;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.bc.response.BcCorpInfoDTO;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.channel.request.tag.CorpTagAdapterDTO;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.channel.request.tag.CorpTagGroupAdapterDTO;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.channel.request.tag.MarkCropTagDTO;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.channel.response.CorpTagGroup;
import com.weimob.mcloud.wechatwork.core.adapter.service.BcAdapterService;
import com.weimob.mcloud.wechatwork.core.entity.privatesphere.PrivateSphere;
import com.weimob.mcloud.wechatwork.core.entity.relation.customer.Customer;
import com.weimob.mcloud.wechatwork.core.entity.relation.employee.Employee;
import com.weimob.mcloud.wechatwork.core.entity.relation.tag.CustomerTag;
import com.weimob.mcloud.wechatwork.core.entity.relation.tag.Tag;
import com.weimob.mcloud.wechatwork.core.entity.relation.tag.TagDetail;
import com.weimob.mcloud.wechatwork.core.entity.relation.tag.TagGroup;
import com.weimob.mcloud.wechatwork.core.service.privatesphere.PrivateSphereService;
import com.weimob.mcloud.wechatwork.customer.check.CustomerTagCheck;
import com.weimob.mcloud.wechatwork.customer.convertor.tag.CustomerTagCovert;
import com.weimob.mcloud.wechatwork.customer.convertor.tag.TagConvert;
import com.weimob.mcloud.wechatwork.customer.convertor.tag.TagGroupConvert;
import com.weimob.mcloud.wechatwork.customer.domain.dto.CorpExternalUserTag;
import com.weimob.mcloud.wechatwork.customer.externalDependencyProxy.privateSphere.PrivateSphereServiceProxy;
import com.weimob.mcloud.wechatwork.customer.facade.impl.customer.CustomerFacadeV2;
import com.weimob.mcloud.wechatwork.customer.mq.product.TagChangeMsgProduct;
import com.weimob.mcloud.wechatwork.customer.service.ChannelTagService;
import com.weimob.mcloud.wechatwork.customer.service.CustomerEmployeeTagService;
import com.weimob.mcloud.wechatwork.customer.service.TagBaseService;
import com.weimob.mcloud.wechatwork.customer.service.TagManageService;
import com.weimob.mcloud.wechatwork.customer.service.user.constant.TagConstant;
import com.weimob.mcloud.wechatwork.customer.service.user.enums.TagSourceEnum;
import com.weimob.mcloud.wechatwork.customer.service.user.enums.tag.TagChangeEnum;
import com.weimob.mcloud.wechatwork.customer.service.user.exception.BizException;
import com.weimob.mcloud.wechatwork.customer.service.user.module.dto.tag.v2.*;
import com.weimob.mcloud.wechatwork.customer.service.user.module.msgBody.CorpCustomerTagChangeBody;
import com.weimob.mcloud.wechatwork.customer.service.user.module.msgBody.TagChangeBody;
import com.weimob.mcloud.wechatwork.customer.service.user.service.ChannelTagClient;
import com.weimob.mcloud.wechatwork.customer.third.BosThird;
import com.weimob.mcloud.wechatwork.customer.third.customer.CustomerThird;
import com.weimob.mcloud.wechatwork.customer.third.tag.CorpTagThird;
import com.weimob.soa.common.response.SoaResponse;
import com.weimob.soa.common.utils.SoaUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.weimob.mcloud.wechatwork.customer.service.user.constant.TagConstant.TAG_CHANGE;
import static com.weimob.mcloud.wechatwork.customer.service.user.constant.TagConstant.TAG_GROUP_CHANGE;
import static com.weimob.mcloud.wechatwork.customer.service.user.enums.TagBizErrorEnum.*;

/**
 * @author junlong.lv
 * @version 1.0
 * @date 2022/3/14 2:33 下午
 */
@Service
@Slf4j
public class ChannelTagClientImpl implements ChannelTagClient {

    @Autowired
    private ChannelTagService channelTagService;

    @Resource
    private BcAdapterService bcAdapterService;

    @Autowired
    private TagBaseService tagBaseService;

    @Autowired
    private CorpTagThird corpTagThird;

    @Autowired
    private CustomerThird customerThird;

    @Autowired
    private BosThird bosThird;

    @Autowired
    private TagChangeMsgProduct tagChangeMsgProduct;

    @Reference
    private PrivateSphereService privateSphereService;

    @Autowired
    private TagManageService tagManageService;

    @Autowired
    @Qualifier("syncCustomerTagToTX")
    private ThreadPoolTaskExecutor syncCustomerTagToTX;

    @Autowired
    private CustomerFacadeV2 customerFacadeV2;

    /**
     * 企微助手产品id
     */
    @Value("${aewc.productId:203}")
    private Long aewcProductId;

    @Autowired
    private CustomerEmployeeTagService customerEmployeeTagService;

    @Autowired
    private PrivateSphereServiceProxy privateSphereServiceProxy;

    @Override
    public SoaResponse<CorpTagGroupDTO, ?> addCorpTag(CorpTagGroupDTO corpTagGroupDTO) {

        if (Objects.isNull(corpTagGroupDTO)) {
            throw new BizException("参数不允许为空");
        }

        if (StringUtils.isBlank(corpTagGroupDTO.getCorpId())) {
            return SoaUtil.error(CORP_ID_NOT_EXIT.getCode(), CORP_ID_NOT_EXIT.getDesc(), null);
        }

        if (StringUtils.isBlank(corpTagGroupDTO.getCorpTagGroupId())
                && StringUtils.isBlank(corpTagGroupDTO.getTagGroupName())) {
            return SoaUtil.error(TAG_GROUP_NAME_IS_NOT_EMPTY.getCode(), TAG_GROUP_NAME_IS_NOT_EMPTY.getDesc(), null);
        }

        List<CorpTagDTO> tagListRequest = corpTagGroupDTO.getTagList();
        if (CollectionUtils.isEmpty(tagListRequest)) {
            return SoaUtil.error(TAG_GROUP_NOT_HAVE_TAG.getCode(), TAG_GROUP_NOT_HAVE_TAG.getDesc(), null);
        }

        PrivateSphere request = new PrivateSphere();
        request.setCorpId(corpTagGroupDTO.getCorpId());
        request.setBosId(corpTagGroupDTO.getBosId());
        request.setProductId(aewcProductId);
        SoaResponse<PrivateSphere, Void> fetchSoa = privateSphereService.fetch(request);
        if (0L != Long.parseLong(fetchSoa.getReturnCode())) {
            return SoaUtil.error(AUTHORIZE_AUTH.getCode(), AUTHORIZE_AUTH.getDesc(), null);
        }

        PrivateSphere responseVo = fetchSoa.getResponseVo();

        SoaResponse<CorpTagGroupAdapterDTO, Void> corpTagGroupAdapterDTOVoidSoaResponse =
                channelTagService.addCorpTag(corpTagGroupDTO, responseVo);
        if (0L != Long.parseLong(corpTagGroupAdapterDTOVoidSoaResponse.getReturnCode())) {
            return SoaUtil.error(corpTagGroupAdapterDTOVoidSoaResponse.getReturnCode(), corpTagGroupAdapterDTOVoidSoaResponse.getReturnMsg(), null);
        }

        CorpTagGroupAdapterDTO unpack = SoaUtil.unpack(corpTagGroupAdapterDTOVoidSoaResponse);
        if (Objects.isNull(unpack)) {
            return SoaUtil.ok(null);
        }

        CorpTagGroupDTO corpTagGroupDTOResponse = TagConvert.toCorpTagGroupDTO(unpack);

        TagGroup tagGroup = new TagGroup();
        tagGroup.setCorpId(corpTagGroupDTO.getCorpId());
        tagGroup.setExternalTagGroupId(corpTagGroupDTOResponse.getCorpTagGroupId());
        tagGroup.setTagGroupName(corpTagGroupDTOResponse.getTagGroupName());
        tagGroup.setDeleted(false);
        tagGroup.setTagSource(TagSourceEnum.WECHAT.getSource());

        //本地存储标签组 tag_group表
        tagBaseService.batchInsertTagGroup(Lists.newArrayList(tagGroup), corpTagGroupDTO.getCorpId());


        //本地存储标签 tag表
        List<CorpTagDTO> corpTagDTOList = corpTagGroupDTOResponse.getTagList();
        if (CollectionUtils.isNotEmpty(corpTagDTOList)) {

            List<Tag> tagList = new ArrayList<>();
            for (CorpTagDTO corpTagDTO : corpTagDTOList) {
                Tag tag = new Tag();
                tag.setCorpId(corpTagGroupDTO.getCorpId());
                tag.setTagSource(TagSourceEnum.WECHAT.getSource());
                tag.setDeleted(false);
                tag.setExternalTagId(corpTagDTO.getCorpTagId());
                tag.setTagName(corpTagDTO.getTagName());
                tag.setTagGroup(tagGroup);
                tagList.add(tag);
            }

            tagBaseService.batchInsertTag(tagList, corpTagGroupDTO.getCorpId());
        }

        try {
            //发消息
            sendAddMessage(corpTagGroupDTO.getCorpId(), unpack);
        } catch (Exception e) {
            log.error("发送添加标签消息失败, request:{}, error:{}", JSON.toJSONString(unpack), e);
        }
        

        return SoaUtil.ok(corpTagGroupDTOResponse);
    }

    @Override
    public SoaResponse<Boolean, ?> editCorpTag(EditCorpTagDTO editCorpTagDTO) {

        if (StringUtils.isBlank(editCorpTagDTO.getCorpId())) {
            return SoaUtil.error(CORP_ID_NOT_EXIT.getCode(), CORP_ID_NOT_EXIT.getDesc(), false);
        }

        if (Objects.isNull(editCorpTagDTO.getBosId())) {
            return SoaUtil.error(BO_ID_NOT_EXIT.getCode(), BO_ID_NOT_EXIT.getDesc(), false);
        }

        if (StringUtils.isBlank(editCorpTagDTO.getCorpTagId())) {
            return SoaUtil.error(TAG_ID_NOT_EMPTY.getCode(), TAG_ID_NOT_EMPTY.getDesc(), false);
        }

        if (StringUtils.isBlank(editCorpTagDTO.getTagName())) {
            return SoaUtil.error(TAG_NAME_NOT_EMPTY.getCode(), TAG_NAME_NOT_EMPTY.getDesc(), false);
        }

        PrivateSphere request = new PrivateSphere();
        request.setCorpId(editCorpTagDTO.getCorpId());
        request.setBosId(editCorpTagDTO.getBosId());
        request.setProductId(aewcProductId);
        SoaResponse<PrivateSphere, Void> fetchSoa = privateSphereService.fetch(request);
        if (0L != Long.parseLong(fetchSoa.getReturnCode())) {
            return SoaUtil.error(AUTHORIZE_AUTH.getCode(), AUTHORIZE_AUTH.getDesc(), false);
        }

        PrivateSphere privateSphere = fetchSoa.getResponseVo();

        String groupId = null;
        List<Tag> tagList = tagBaseService.queryTagByTagIds(editCorpTagDTO.getCorpId(), Lists.newArrayList(editCorpTagDTO.getCorpTagId()), false);
        if (CollectionUtils.isEmpty(tagList)) {
            //该企微官方标签在本地不存在, 需要查询渠道
            CorpTagGroup corpTagGroup = corpTagThird.getChannelTagGroup(privateSphere, TagConstant.TAG_CHANGE, editCorpTagDTO.getCorpTagId());
            if (Objects.isNull(corpTagGroup)) {
                return SoaUtil.error(TAG_NOT_EXIT.getCode(), TAG_NOT_EXIT.getDesc(), false);
            }

            groupId = corpTagGroup.getGroupId();

        } else {
            TagGroup tagGroup = tagList.get(0).getTagGroup();
            groupId = tagGroup.getExternalTagGroupId();
        }

        EditCorpTagOrGroup editCorpTagOrGroup = new EditCorpTagOrGroup();
        editCorpTagOrGroup.setId(editCorpTagDTO.getCorpTagId());
        editCorpTagOrGroup.setName(editCorpTagDTO.getTagName());
        editCorpTagOrGroup.setTagType(TAG_CHANGE);
        editCorpTagOrGroup.setCorpId(editCorpTagDTO.getCorpId());
        editCorpTagOrGroup.setBosId(editCorpTagDTO.getBosId());
        SoaResponse<Boolean, ?> booleanSoaResponse = channelTagService.editCorpTag(editCorpTagOrGroup, privateSphere);
        if (0L != Long.parseLong(booleanSoaResponse.getReturnCode())) {
            return booleanSoaResponse;
        }

        TagGroup tagGroup = new TagGroup();
        tagGroup.setTagSource(TagSourceEnum.WECHAT.getSource());
        tagGroup.setExternalTagGroupId(groupId);

        Tag tag = new Tag();
        tag.setCorpId(editCorpTagDTO.getCorpId());
        tag.setTagGroup(tagGroup);
        tag.setExternalTagId(editCorpTagDTO.getCorpTagId());
        tag.setTagName(editCorpTagDTO.getTagName());
        tag.setDeleted(false);
        tag.setTagSource(TagSourceEnum.WECHAT.getSource());

        tagBaseService.batchUpdateTag(Lists.newArrayList(tag), editCorpTagDTO.getCorpId());

        try {
            sendEditTagMsg(editCorpTagDTO.getCorpId(), editCorpTagDTO);
        } catch (Exception e) {
            log.error("发送编辑标签消息失败, request:{}, error:{}", JSON.toJSONString(editCorpTagDTO), e);
        }

        return SoaUtil.ok(true);
    }

    private void sendEditTagMsg(String corpId, EditCorpTagDTO editCorpTagDTO) {
        Set<Long> bosIds = bosThird.getBosIdListByCorpId(corpId);

        if (CollectionUtils.isEmpty(bosIds)) {
            log.error("实时监听企微官方添加标签消息, 根据corpId查询bosId, 没有查到, corpId:{}", corpId);
            return;
        }

        for (Long bosId : bosIds) {
            TagChangeBody tagChangeBody = new TagChangeBody();
            tagChangeBody.setCorpId(corpId);
            tagChangeBody.setBosId(bosId);
            tagChangeBody.setCorpTagId(editCorpTagDTO.getCorpTagId());
            tagChangeBody.setTagName(editCorpTagDTO.getTagName());
            tagChangeBody.setTagChangeType(TagChangeEnum.TAG_EDIT.getType());
            tagChangeMsgProduct.sendTagChangeMsg(tagChangeBody);
        }

    }

    @Override
    public SoaResponse<Boolean, ?> editCorpTagGroup(EditCorpTagGroupDTO editCorpTagGroupDTO) {

        if (StringUtils.isBlank(editCorpTagGroupDTO.getCorpId())) {
            return SoaUtil.error(CORP_ID_NOT_EXIT.getCode(), CORP_ID_NOT_EXIT.getDesc(), false);
        }

        if (Objects.isNull(editCorpTagGroupDTO.getBosId())) {
            return SoaUtil.error(BO_ID_NOT_EXIT.getCode(), BO_ID_NOT_EXIT.getDesc(), false);
        }

        if (StringUtils.isBlank(editCorpTagGroupDTO.getCorpTagGroupId())) {
            return SoaUtil.error(TAG_GROUP_ID_IS_NOT_EMPTY.getCode(), TAG_GROUP_ID_IS_NOT_EMPTY.getDesc(), false);
        }

        if (StringUtils.isBlank(editCorpTagGroupDTO.getTagGroupName())) {
            return SoaUtil.error(TAG_GROUP_NAME_IS_NOT_EMPTY.getCode(), TAG_GROUP_NAME_IS_NOT_EMPTY.getDesc(), false);
        }

        PrivateSphere request = new PrivateSphere();
        request.setCorpId(editCorpTagGroupDTO.getCorpId());
        request.setProductId(aewcProductId);
        request.setBosId(editCorpTagGroupDTO.getBosId());
        SoaResponse<PrivateSphere, Void> fetchSoa = privateSphereService.fetch(request);
        if (0L != Long.parseLong(fetchSoa.getReturnCode())) {
            return SoaUtil.error(AUTHORIZE_AUTH.getCode(), AUTHORIZE_AUTH.getDesc(), false);
        }

        PrivateSphere responseVo = fetchSoa.getResponseVo();

        List<TagGroup> tagGroupList = tagBaseService.queryGroupByGroupIds(editCorpTagGroupDTO.getCorpId(), Lists.newArrayList(editCorpTagGroupDTO.getCorpTagGroupId()));
        if (CollectionUtils.isEmpty(tagGroupList)) {
            //该企微官方标签标签组不存在，去渠道查询
            CorpTagGroup corpTagGroup = corpTagThird.getChannelTagGroup(responseVo, TAG_GROUP_CHANGE,
                    editCorpTagGroupDTO.getCorpTagGroupId());
            if (Objects.isNull(corpTagGroup)) {
                return SoaUtil.error(TAG_GROUP_NOT_EXIT.getCode(), TAG_GROUP_NOT_EXIT.getDesc(), false);
            }
        }

        EditCorpTagOrGroup editCorpTagOrGroup = new EditCorpTagOrGroup();
        editCorpTagOrGroup.setId(editCorpTagGroupDTO.getCorpTagGroupId());
        editCorpTagOrGroup.setName(editCorpTagGroupDTO.getTagGroupName());
        editCorpTagOrGroup.setTagType(TAG_GROUP_CHANGE);
        editCorpTagOrGroup.setCorpId(editCorpTagGroupDTO.getCorpId());
        editCorpTagOrGroup.setBosId(editCorpTagGroupDTO.getBosId());
        SoaResponse<Boolean, ?> booleanSoaResponse = channelTagService.editCorpTag(editCorpTagOrGroup, responseVo);

        if (0L != Long.parseLong(booleanSoaResponse.getReturnCode())) {
            return booleanSoaResponse;
        }

        TagGroup tagGroup = new TagGroup();
        tagGroup.setCorpId(editCorpTagGroupDTO.getCorpId());
        tagGroup.setExternalTagGroupId(editCorpTagGroupDTO.getCorpTagGroupId());
        tagGroup.setTagGroupName(editCorpTagGroupDTO.getTagGroupName());
        tagGroup.setTagSource(TagSourceEnum.WECHAT.getSource());
        tagGroup.setDeleted(false);
        tagBaseService.batchUpdateTagGroup(Lists.newArrayList(tagGroup), editCorpTagGroupDTO.getCorpId());

        try {
            sendEditTagGroupMsg(editCorpTagGroupDTO.getCorpId(), editCorpTagGroupDTO);
        } catch (Exception e) {
            log.error("发送标签编辑消息失败, request:{}, error:{}", JSON.toJSONString(editCorpTagGroupDTO), e);
        }


        return SoaUtil.ok(true);
    }

    private void sendEditTagGroupMsg(String corpId, EditCorpTagGroupDTO editCorpTagGroupDTO) {
        Set<Long> bosIds = bosThird.getBosIdListByCorpId(corpId);

        if (CollectionUtils.isEmpty(bosIds)) {
            log.error("实时监听企微官方添加标签消息, 根据corpId查询bosId, 没有查到, corpId:{}", corpId);
            return;
        }

        for (Long bosId : bosIds) {
            TagChangeBody tagChangeBody = new TagChangeBody();
            tagChangeBody.setCorpId(corpId);
            tagChangeBody.setBosId(bosId);
            tagChangeBody.setCorpTagGroupId(editCorpTagGroupDTO.getCorpTagGroupId());
            tagChangeBody.setTagGroupName(editCorpTagGroupDTO.getTagGroupName());
            tagChangeBody.setTagChangeType(TagChangeEnum.TAG_GROUP_EDIT.getType());
            tagChangeMsgProduct.sendTagChangeMsg(tagChangeBody);
        }

    }

    @Override
    public SoaResponse<Boolean, ?> delCorpTag(DelCorpTagDTO delCorpTagDTO) {
        if (StringUtils.isBlank(delCorpTagDTO.getCorpId())) {
            return SoaUtil.error(CORP_ID_NOT_EXIT.getCode(), CORP_ID_NOT_EXIT.getDesc(), false);
        }

        PrivateSphere request = new PrivateSphere();
        request.setCorpId(delCorpTagDTO.getCorpId());
        request.setBosId(delCorpTagDTO.getBosId());
        request.setProductId(aewcProductId);
        SoaResponse<PrivateSphere, Void> fetchSoa = privateSphereService.fetch(request);
        if (0L != Long.parseLong(fetchSoa.getReturnCode())) {
            return SoaUtil.error(AUTHORIZE_AUTH.getCode(), AUTHORIZE_AUTH.getDesc(), false);
        }

        PrivateSphere responseVo = fetchSoa.getResponseVo();

        SoaResponse<Boolean, ?> booleanSoaResponse = channelTagService.delCorpTag(delCorpTagDTO, responseVo);
        if (0L != Long.parseLong(booleanSoaResponse.getReturnCode())) {
            return booleanSoaResponse;
        }

        if (CollectionUtils.isNotEmpty(delCorpTagDTO.getGroupIdList())) {
            List<TagGroup> tagGroupList = tagBaseService.queryGroupByGroupIds(delCorpTagDTO.getCorpId(), delCorpTagDTO.getGroupIdList());
            if (CollectionUtils.isNotEmpty(tagGroupList)) {
                Set<String> groupIds = TagGroupConvert.toCorpGroupIds(tagGroupList);
                if (CollectionUtils.isNotEmpty(groupIds)) {
                    tagBaseService.deletedTagGroupByGroupIds(delCorpTagDTO.getCorpId(), Lists.newArrayList(groupIds));
                }
            }
        }

        if (CollectionUtils.isNotEmpty(delCorpTagDTO.getTagIdList())) {
            List<Tag> tagList = tagBaseService.queryTagByTagIds(delCorpTagDTO.getCorpId(), delCorpTagDTO.getTagIdList(), false);
            if (CollectionUtils.isNotEmpty(tagList)) {
                Set<String> tagIds = TagConvert.toTagIds(tagList);
                if (CollectionUtils.isNotEmpty(tagIds)) {
                    tagBaseService.deletedTagByTagIds(delCorpTagDTO.getCorpId(), Lists.newArrayList(tagIds));
                }

            }
        }

        try {
            sendDeleteMsg(delCorpTagDTO.getCorpId(), delCorpTagDTO);
        } catch (Exception e) {
            log.error("推送消息失败, request:{}, error:{}", JSON.toJSONString(delCorpTagDTO), e);
        }

        return SoaUtil.ok(true);
    }

    private void sendDeleteMsg(String corpId, DelCorpTagDTO delCorpTagDTO) {
        Set<Long> bosIds = bosThird.getBosIdListByCorpId(corpId);

        if (CollectionUtils.isEmpty(bosIds)) {
            log.error("实时监听企微官方添加标签消息, 根据corpId查询bosId, 没有查到, corpId:{}", corpId);
            return;
        }

        for (Long bosId : bosIds) {

            if (CollectionUtils.isNotEmpty(delCorpTagDTO.getGroupIdList())) {
                for (String groupId : delCorpTagDTO.getGroupIdList()) {
                    TagChangeBody tagChangeBody = new TagChangeBody();
                    tagChangeBody.setCorpId(corpId);
                    tagChangeBody.setBosId(bosId);
                    tagChangeBody.setCorpTagGroupId(groupId);
                    tagChangeBody.setTagChangeType(TagChangeEnum.TAG_GROUP_DELETE.getType());
                    tagChangeMsgProduct.sendTagChangeMsg(tagChangeBody);
                }

            }

            if (CollectionUtils.isNotEmpty(delCorpTagDTO.getTagIdList())) {
                for (String tagId : delCorpTagDTO.getTagIdList()) {
                    TagChangeBody tagChangeBody = new TagChangeBody();
                    tagChangeBody.setCorpId(corpId);
                    tagChangeBody.setBosId(bosId);
                    tagChangeBody.setCorpTagId(tagId);
                    tagChangeBody.setTagChangeType(TagChangeEnum.TAG_DELETE.getType());
                    tagChangeMsgProduct.sendTagChangeMsg(tagChangeBody);
                }

            }

        }

    }

    @Override
    public SoaResponse<Boolean, ?> addUserTag(CustomerCorpTagDTO customerCorpTagDTO) {

        log.info("给客户打企微标签, request:{}", JSON.toJSONString(customerCorpTagDTO));

        //检查请求参数合法性
        Long bosId = customerCorpTagDTO.getBosId();
        CustomerTagCheck.checkAddUserTag(customerCorpTagDTO);


        //查询私域信息, 没有买企微助手的店铺是不允许走企微助手进行同步客户标签数据的
        PrivateSphere privateSphere = privateSphereServiceProxy.queryPrivateSphere(bosId);

        if (!customerCorpTagDTO.getCorpId().equals(privateSphere.getCorpId())) {
            return SoaUtil.error(BO_ID_CORP_ID_ERROR.getCode(), BO_ID_CORP_ID_ERROR.getDesc(), false);
        }

        //获取要打的标签corpTagId
        Set<String> corpTagIds = TagConvert.toCorpTagId(customerCorpTagDTO);
        if (CollectionUtils.isEmpty(corpTagIds)) {
            return SoaUtil.error(TAG_ID_NOT_EMPTY.getCode(), TAG_ID_NOT_EMPTY.getDesc(), false);
        }

        //key:corpTagId; value:tagGroupId
        Map<String, String> corpTagIdAndGroupIdMap = getCorpTagIdAndGroupIdMap(privateSphere.getCorpId(), corpTagIds);

        //外部联系人id转换, 如果没有传externalUserId, 就根据wid去passport换externalUserId
        String externalUserId = customerCorpTagDTO.getExternalUserId();
        String customerId = null;
        if (StringUtils.isBlank(externalUserId)) {
            Customer customer = queryCustomerByWid(privateSphere, customerCorpTagDTO.getWid());
            externalUserId = customer.getExternalUserid();
            customerId = customer.getId();
        }


        //查询与该客户拥有好友关系的所有员工
        Map<String, String> txUserIdAndOrgUserIdMap = queryCustomerRelate(privateSphere, customerCorpTagDTO, customerId);


        //查询本地，根据userId + externalUserId查询
        List<TagDetail> nativeTagDetailList = customerEmployeeTagService.fetchCustomerEmployeeTag(privateSphere, externalUserId, null, true);

        Map<String, List<TagDetail>> tagDetailMap = CustomerTagCovert.toOrgUserIdAndCustomerTagMap(nativeTagDetailList);

        //处理新员工&客户&标签关系表
        compareAddOrRemoveCustomerEmployeeTag(privateSphere, externalUserId, customerCorpTagDTO, nativeTagDetailList, txUserIdAndOrgUserIdMap);

        //处理客户标签表关系数据
        compareAddOrRemoveCustomerTag(privateSphere, externalUserId, customerCorpTagDTO);


        //同步腾讯客户标签关系
        syncCustomerTag2TX(privateSphere, txUserIdAndOrgUserIdMap, externalUserId, customerCorpTagDTO, tagDetailMap);

        //发送客户标签变更消息，目前只有cdp在消费
        sendCustomerTagChangeMsg(privateSphere, txUserIdAndOrgUserIdMap, externalUserId, customerCorpTagDTO, corpTagIdAndGroupIdMap, tagDetailMap);

        return SoaUtil.ok(true);
    }

    private void compareAddOrRemoveCustomerTag(PrivateSphere privateSphere, String externalUserId, CustomerCorpTagDTO customerCorpTagDTO) {
        if (Objects.isNull(privateSphere) || StringUtils.isBlank(externalUserId) || null == customerCorpTagDTO) {
            return;
        }

        CustomerTag customerTag = customerEmployeeTagService.getCustomerTag(privateSphere, externalUserId);

        List<String> dbCustomerTagIdList = new ArrayList<>();
        if (null != customerTag && CollectionUtils.isNotEmpty(customerTag.getTagIds())) {
            dbCustomerTagIdList = Lists.newArrayList(customerTag.getTagIds());
        }

        List<CorpTagDTO> addTagList = customerCorpTagDTO.getAddTagList();
        List<String> addTagIdList = TagConvert.toCorpTagIdList(addTagList);

        List<CorpTagDTO> removeTagList = customerCorpTagDTO.getRemoveTagList();
        List<String> removeTagIdList = TagConvert.toCorpTagIdList(removeTagList);

        List<String> analysisTagIdList = analysisTagIdList(dbCustomerTagIdList, addTagIdList, removeTagIdList);
        if (CollectionUtils.isNotEmpty(analysisTagIdList)) {
            analysisTagIdList = analysisTagIdList.stream().distinct().collect(Collectors.toList());
        }

        customerEmployeeTagService.updateCustomerTag(privateSphere, externalUserId, analysisTagIdList);

    }

    private void compareAddOrRemoveCustomerEmployeeTag(PrivateSphere privateSphere, String externalUserId, CustomerCorpTagDTO customerCorpTagDTO, List<TagDetail> nativeTagDetailList,
                                                Map<String, String> txUserIdAndOrgUserIdMap) {
        if (Objects.isNull(privateSphere) || StringUtils.isBlank(externalUserId)
                || null == customerCorpTagDTO || MapUtils.isEmpty(txUserIdAndOrgUserIdMap)) {
            return;
        }

        Map<String, List<TagDetail>> orgUserIdAndCustomerTagMap = CustomerTagCovert.toOrgUserIdAndCustomerTagMap(nativeTagDetailList);

        List<CorpTagDTO> addTagList = customerCorpTagDTO.getAddTagList();
        List<String> addTagIdList = TagConvert.toCorpTagIdList(addTagList);

        List<CorpTagDTO> removeTagList = customerCorpTagDTO.getRemoveTagList();
        List<String> removeTagIdList = TagConvert.toCorpTagIdList(removeTagList);

        for (Map.Entry<String, String> entry : txUserIdAndOrgUserIdMap.entrySet()) {
            String orgUserId = entry.getValue();

            List<TagDetail> tagDetailList = orgUserIdAndCustomerTagMap.get(orgUserId);
            List<String> dbTagIdList = CustomerTagCovert.toTagIds(tagDetailList);

            List<String> analysisTagIdList = analysisTagIdList(dbTagIdList, addTagIdList, removeTagIdList);
            if (CollectionUtils.isNotEmpty(analysisTagIdList)) {
                analysisTagIdList = analysisTagIdList.stream().distinct().collect(Collectors.toList());
            }
            customerEmployeeTagService.updateCustomerEmployeeTag(privateSphere, externalUserId, orgUserId, analysisTagIdList);
        }

    }

    private List<String> analysisTagIdList(List<String> dbTagIdList, List<String> addTagIdList, List<String> removeTagIdList) {
        if (CollectionUtils.isEmpty(dbTagIdList)) {
            return addTagIdList;
        }

        if (CollectionUtils.isNotEmpty(addTagIdList)) {
            dbTagIdList.addAll(addTagIdList);
        }

        if (CollectionUtils.isEmpty(removeTagIdList)) {
            return dbTagIdList;
        } else {
            List<String> result = new ArrayList<>();
            for (String tagId : dbTagIdList) {
                if (!removeTagIdList.contains(tagId)) {
                    result.add(tagId);
                }
            }

            return result;
        }
    }

    private void syncCustomerTag2TX(PrivateSphere privateSphere,  Map<String, String> txUserIdAndOrgUserIdMap, String externalUserId,
                                    CustomerCorpTagDTO customerCorpTagDTO, Map<String, List<TagDetail>> tagDetailMap) {

        for (Map.Entry<String, String> entry : txUserIdAndOrgUserIdMap.entrySet()) {

            String txUserId = entry.getKey();
            String orgUserId = entry.getValue();


            CorpExternalUserTag corpExternalUserTag = buildCorpExternalUserTag(tagDetailMap, externalUserId, orgUserId, txUserId, customerCorpTagDTO);
            if (null == corpExternalUserTag) {
                continue;
            }
            corpExternalUserTag.setCorpId(privateSphere.getCorpId());
            corpExternalUserTag.setBosId(privateSphere.getBosId());


            //同步客户标签关系到腾讯
            String finalExternalUserId = externalUserId;
            syncCustomerTagToTX.execute(() -> {
                try {

                    log.info("调用渠道缓冲同步客户标签到腾讯, request:{}", corpExternalUserTag);
                    String type = customerCorpTagDTO.getOffline() ? "offline" : "realtime";
                    SoaResponse<MarkCropTagDTO, Void> voidSoaResponse = channelTagService.addUserTagV2(corpExternalUserTag, null, type);
                    if (0L == Long.parseLong(voidSoaResponse.getReturnCode())) {
                        //打标成功
                        return;

                    } else if (CommonBizErrorEnum.WECHAT_WORK_LIMIT.getCode().equals(voidSoaResponse.getReturnCode())) {

                        //被限频了，不做处理，如果限频最终不成功，企微助手db有，腾讯没有，就需要手动处理了，通过job
                        return;
                    }else if (100300600142L == Long.parseLong(voidSoaResponse.getReturnCode())){
                        
                        log.error("调用渠道缓冲同步客户标签到腾讯, 打标失败, request:{}, response:{}", JSON.toJSONString(corpExternalUserTag), JSON.toJSONString(voidSoaResponse));
                        //本地处理
                        tagManageService.initCustomerTag(privateSphere, finalExternalUserId, null);
                    } else  {

                        //其他异常场景
                        tagManageService.initCustomerTag(privateSphere, finalExternalUserId, null);
                        return;
                    }
                } catch (Exception e) {
                    log.error("调渠道api接口给客户打标签失败, request:{}, error:{}", JSON.toJSONString(corpExternalUserTag), e);
                    tagManageService.initCustomerTag(privateSphere, finalExternalUserId, null);
                }
            });
        }

    }

    private void sendCustomerTagChangeMsg(PrivateSphere privateSphere, Map<String, String> txUserIdAndOrgUserIdMap, String externalUserId, CustomerCorpTagDTO customerCorpTagDTO,
                                           Map<String, String> corpTagIdAndGroupIdMap, Map<String, List<TagDetail>> tagDetailMap) {
        for (Map.Entry<String, String> entry : txUserIdAndOrgUserIdMap.entrySet()) {
            String txUserId = entry.getKey();
            String orgUserId = entry.getValue();

            CorpExternalUserTag corpExternalUserTag = buildCorpExternalUserTag(tagDetailMap, externalUserId, orgUserId, txUserId, customerCorpTagDTO);
            if (null == corpExternalUserTag) {
                continue;
            }
            corpExternalUserTag.setCorpId(privateSphere.getCorpId());
            corpExternalUserTag.setBosId(customerCorpTagDTO.getBosId());

            try {
                //发送客户标签变更消息
                sendUserTagMsg(privateSphere, customerCorpTagDTO.getWid(), externalUserId, txUserId,
                        corpExternalUserTag, corpTagIdAndGroupIdMap);
            } catch (Exception e) {
                log.error("发送客户标签噶虚拟消息失败, request:{}, error:{}", JSON.toJSONString(corpExternalUserTag), e);
            }
        }
    }

    private Customer queryCustomerByWid(PrivateSphere privateSphere, Long wid) {
        //根据wid查询externalUserId, 查询passport
        Set<String> externalUserIdByWids = customerFacadeV2.queryExternalUserIdByWids(privateSphere, Lists.newArrayList(wid));
        if (CollectionUtils.isEmpty(externalUserIdByWids)) {
            throw new BizException(Long.parseLong(QUERY_PASSPORT_CHANGE_EXTERNALUSERID_ERROR.getCode()), QUERY_PASSPORT_CHANGE_EXTERNALUSERID_ERROR.getDesc());
        }


        //根据externalUserId查询客户基本信息，获取customerId
        List<Customer> customerList = customerFacadeV2.querySimpleCustomerByExternalUserIds(privateSphere, Lists.newArrayList(externalUserIdByWids));
        if (CollectionUtils.isEmpty(customerList)) {
            throw new BizException(Long.parseLong(CUSTOMER_WID_NOT_EXIT.getCode()), CUSTOMER_WID_NOT_EXIT.getDesc());
        }

        return customerList.get(0);

    }

    private Map<String, String> queryCustomerRelate(PrivateSphere privateSphere, CustomerCorpTagDTO customerCorpTagDTO, String customerId) {

        Map<String, String> txUserIdAndOrgUserIdMap = new HashMap<>();
        if (StringUtils.isBlank(customerCorpTagDTO.getOrgUserId()) && StringUtils.isBlank(customerCorpTagDTO.getChannelUserId())) {

            List<Employee> relationList = customerThird.getEffectiveRelationList(privateSphere, customerId);
            if (CollectionUtils.isEmpty(relationList)) {

                throw new BizException(Long.parseLong(CUSTOMER_NOT_HAVE_FRIEND.getCode()), CUSTOMER_NOT_HAVE_FRIEND.getDesc());
            }
            for (Employee employee : relationList) {
                txUserIdAndOrgUserIdMap.put(employee.getTxUserId(), employee.getId());
            }

        } else {
            //根据orgUserId查询渠道userId
            Employee employee = customerThird.queryEmployee(privateSphere, customerCorpTagDTO.getChannelUserId(), null);
            if (Objects.isNull(employee) || StringUtils.isBlank(employee.getTxUserId())) {
                throw new BizException(Long.parseLong(TX_USERiD_NOT_EXIT.getCode()), TX_USERiD_NOT_EXIT.getDesc());
            }

            txUserIdAndOrgUserIdMap.put(employee.getTxUserId(), employee.getId());
        }

        return txUserIdAndOrgUserIdMap;
    }


    private Map<String, String> getCorpTagIdAndGroupIdMap(String corpId, Set<String> corpTagIds) {
        if (CollectionUtils.isEmpty(corpTagIds)) {
            return new HashMap<>();
        }

        List<Tag> tagList = tagBaseService.queryTagByTagIds(corpId, Lists.newArrayList(corpTagIds), false);
        return TagConvert.toCorpTagIdAndCorpGroupIdMap(tagList);
    }

    private void sendUserTagMsg(PrivateSphere privateSphere, Long wid, String externalUserId, String txUserId,
                                CorpExternalUserTag corpExternalUserTag, Map<String, String> corpTagIdAndGroupIdMap) {

        if (MapUtils.isEmpty(corpTagIdAndGroupIdMap)) {
            return;
        }


        if (Objects.isNull(privateSphere) || StringUtils.isBlank(privateSphere.getCorpId()) || Objects.isNull(privateSphere.getBosId())) {
            return;
        }

        CorpCustomerTagChangeBody corpCustomerTagChangeBody = new CorpCustomerTagChangeBody();
        corpCustomerTagChangeBody.setCorpId(privateSphere.getCorpId());
        corpCustomerTagChangeBody.setBosId(privateSphere.getBosId());
        corpCustomerTagChangeBody.setWid(wid);
        corpCustomerTagChangeBody.setExternalUserId(externalUserId);
        corpCustomerTagChangeBody.setTxUserId(txUserId);
        corpCustomerTagChangeBody.setOrgUserId(corpExternalUserTag.getUserId());

        List<String> addTag = corpExternalUserTag.getAddTag();

        List<CorpTagDTO> addTagList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(addTag)) {
            for (String addTagId : addTag) {
                String groupId = corpTagIdAndGroupIdMap.get(addTagId);
                if (StringUtils.isBlank(groupId)) {
                    continue;
                }

                CorpTagDTO corpTagDTO = new CorpTagDTO();
                corpTagDTO.setCorpTagId(addTagId);
                CorpTagGroupDTO tagGroupDTO = new CorpTagGroupDTO();
                tagGroupDTO.setCorpTagGroupId(groupId);
                corpTagDTO.setTagGroupDTO(tagGroupDTO);
                addTagList.add(corpTagDTO);
            }
        }
        corpCustomerTagChangeBody.setAddTagList(addTagList);


        List<String> removeTag = corpExternalUserTag.getRemoveTag();
        List<CorpTagDTO> removeTagList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(removeTag)) {
            for (String removeTagId : removeTag) {
                String groupId = corpTagIdAndGroupIdMap.get(removeTagId);
                if (StringUtils.isBlank(groupId)) {
                    continue;
                }

                CorpTagDTO corpTagDTO = new CorpTagDTO();
                corpTagDTO.setCorpTagId(removeTagId);
                CorpTagGroupDTO tagGroupDTO = new CorpTagGroupDTO();
                tagGroupDTO.setCorpTagGroupId(groupId);
                corpTagDTO.setTagGroupDTO(tagGroupDTO);
                removeTagList.add(corpTagDTO);
            }
        }
        corpCustomerTagChangeBody.setRemoveTagList(removeTagList);

        if (CollectionUtils.isEmpty(addTagList) && CollectionUtils.isEmpty(removeTagList)) {
            return;
        }

        tagChangeMsgProduct.sendCorpCustomerTagChangeBody(corpCustomerTagChangeBody);


    }

    private CorpExternalUserTag buildCorpExternalUserTag(Map<String, List<TagDetail>> tagDetailMap, String externalUserId, String orgUserId,
                                                         String txUserId, CustomerCorpTagDTO customerCorpTagDTO) {
        if (MapUtils.isEmpty(tagDetailMap) || CollectionUtils.isEmpty(tagDetailMap.get(orgUserId))) {
            if (CollectionUtils.isEmpty(customerCorpTagDTO.getAddTagList())) {
                return null;
            }
            CorpExternalUserTag corpExternalUserTag = new CorpExternalUserTag();
            corpExternalUserTag.setExternalUserId(externalUserId);
            corpExternalUserTag.setUserId(txUserId);
            corpExternalUserTag.setAddTag(TagConvert.toCorpTagIdList(customerCorpTagDTO.getAddTagList()));
            return corpExternalUserTag;
        }

        List<TagDetail> tagDetailList = tagDetailMap.get(orgUserId);
        Set<String> nativeCorpTagIdSet = CustomerTagCovert.toCorpTagIdSet(tagDetailList);

        Set<String> waitAddTagIds = new HashSet<>();
        Set<String> waitRemoveTagIds = new HashSet<>();

        List<String> addTagIdsTarget = TagConvert.toCorpTagIdList(customerCorpTagDTO.getAddTagList());
        List<String> removeTagIdsTarget = TagConvert.toCorpTagIdList(customerCorpTagDTO.getRemoveTagList());


        if (CollectionUtils.isNotEmpty(addTagIdsTarget)) {
            for (String addTagIdTarget : addTagIdsTarget) {
                if (!nativeCorpTagIdSet.contains(addTagIdTarget)) {
                    waitAddTagIds.add(addTagIdTarget);
                }
            }
        }

        if (CollectionUtils.isNotEmpty(removeTagIdsTarget)) {
            for (String removeTagId : removeTagIdsTarget) {
                if (nativeCorpTagIdSet.contains(removeTagId)) {
                    waitRemoveTagIds.add(removeTagId);
                }
            }
        }

        if (CollectionUtils.isEmpty(waitAddTagIds) && CollectionUtils.isEmpty(waitRemoveTagIds)) {
            return null;
        }

        CorpExternalUserTag corpExternalUserTag = new CorpExternalUserTag();
        corpExternalUserTag.setExternalUserId(externalUserId);
        corpExternalUserTag.setUserId(txUserId);
        if (CollectionUtils.isNotEmpty(waitAddTagIds)) {
            corpExternalUserTag.setAddTag(Lists.newArrayList(waitAddTagIds));
        }

        if (CollectionUtils.isNotEmpty(waitRemoveTagIds)) {
            corpExternalUserTag.setRemoveTag(Lists.newArrayList(waitRemoveTagIds));
        }

        return corpExternalUserTag;
    }

    private String getCorpIdByBosId(Long bosId) {
        // 查询企微号
        BcGetCorpByPidOrBosIdRequestDTO requestDTO = new BcGetCorpByPidOrBosIdRequestDTO();
        requestDTO.setBosId(bosId);

        SoaResponse<List<BcCorpInfoDTO>, Void> corpInfoResponse = bcAdapterService.getCorpInfoListByPidOrBosId(requestDTO);
        log.info("根据pid查询corpId, bosId:{}, response:{}", bosId, JSONObject.toJSONString(corpInfoResponse));
        List<BcCorpInfoDTO> corpInfoList = corpInfoResponse.getResponseVo();
        if (CollectionUtils.isEmpty(corpInfoList)) {
            // 说明当前 pid没有绑定企微号
            return null;
        }
        return corpInfoList.get(0).getCorpId();
    }

    private void sendAddMessage(String corpId, CorpTagGroupAdapterDTO corpTagGroupAdapterDTO) {
        Set<Long> bosIds = bosThird.getBosIdListByCorpId(corpId);
        log.info("根据corpId获取bosId, corpId:{}, response:{}", corpId, JSON.toJSONString(bosIds));

        if (CollectionUtils.isEmpty(bosIds)) {
            log.error("实时监听企微官方添加标签消息, 根据corpId查询bosId, 没有查到, corpId:{}", corpId);
            return;
        }

        if (CollectionUtils.isEmpty(corpTagGroupAdapterDTO.getTagList())) {
            return;
        }

        for (Long bosId : bosIds) {
            List<CorpTagAdapterDTO> tagList = corpTagGroupAdapterDTO.getTagList();

            for (CorpTagAdapterDTO corpTagAdapterDTO : tagList) {
                TagChangeBody tagChangeBody = new TagChangeBody();
                tagChangeBody.setCorpId(corpId);
                tagChangeBody.setBosId(bosId);
                tagChangeBody.setCorpTagGroupId(corpTagGroupAdapterDTO.getGroupId());
                tagChangeBody.setTagGroupName(corpTagGroupAdapterDTO.getGroupName());
                tagChangeBody.setCorpTagId(corpTagAdapterDTO.getTagId());
                tagChangeBody.setTagName(corpTagAdapterDTO.getTagName());
                tagChangeBody.setTagChangeType(TagChangeEnum.TAG_CREATE.getType());
                tagChangeMsgProduct.sendTagChangeMsg(tagChangeBody);
            }
        }
    }
}
